
#include "Perus.h"

#define MAIN_CHUNK                  0x4D4D
#define _3D_EDITOR_CHUNK            0x3D3D
#define OBJECT_BLOCK                0x4000
#define TRIANGULAR_MESH             0x4100
#define VERTICES_LIST               0x4110
#define FACES_DESCRIPTION           0x4120
//#define FACES_MATERIAL              0x4130
#define MAPPING_COORDINATES_LIST    0x4140


bool LataaFontinLeveydet( char *TiedostoNimi, int Leveydet[257] )
{
    ifstream Tiedosto(TiedostoNimi );

    if(Tiedosto.is_open())
    {
        for(int i=0; i<257; i++)
        {
            char Sana[16];
            Tiedosto.getline( Sana, 16, '\n' );
            Leveydet[i] = atoi( Sana );
        }

        return true;
    }else
    {
        return false;
    }      
}




bool LataaLista( char *TiedostoNimi, char *&Lista )
{
    ifstream Tiedosto(TiedostoNimi );

    if(Tiedosto.is_open())
    {
        Lista = new char [99999];
        Tiedosto.getline(Lista, 99999, EOF);

        return true;
    }else
    {
        return false;
    }        
}


bool LataaTGA(char *TiedostoNimi, TEKSTUURI &Tekstuuri )
{
    bool LatausOnnistunut = false;
    
    TGA Tga;
    
    //Run-lenght Encoding:n
    long ImageTotalPixelCount = 0;
    unsigned char Packet;
    unsigned char PacketPixelCount;
    unsigned char RLEComponents[4]; //RGB(A)
    
    char *TheTGASignature = { "TRUEVISION-XFILE." };

    ifstream Tiedosto(TiedostoNimi, ios_base::binary);
    if(Tiedosto.is_open())
    {
        Tiedosto.read((char *)&Tga.IDLenght, 1);
        
        Tiedosto.read((char *)&Tga.ColorMapType, 1);
        if(Tga.ColorMapType != 0){ return false; }  //jos TGA ei ole ColorMapiton: VIRHE
        
        //Tuetut TGA Tyypit: 2 (Uncompressed TrueColor) ja 10 (RLE TrueColor)
        Tiedosto.read((char *)&Tga.ImageType, 1);
        
        //hypätään ColorMapin tietojen yli...
        Tiedosto.seekg( 5, ios_base::cur);

        //hypätään kuvan sijaintikoordinaattien yli...
        Tiedosto.seekg( 4, ios_base::cur);
        
        Tiedosto.read((char *)&Tga.ImageWidth, 2);
        
        Tiedosto.read((char *)&Tga.ImageHeight, 2);
        
        Tiedosto.read((char *)&Tga.PixelDepth, 1);
        if(Tga.PixelDepth != 24 && Tga.PixelDepth != 32){ return false; }
        Tga.Components = Tga.PixelDepth/8;

        //hypätään ImageDescriptorin yli...
        Tiedosto.seekg( 1, ios_base::cur);

        //hypätään Image ID jutskan yli...
        Tiedosto.seekg( Tga.IDLenght, ios_base::cur);
        
        //jos TGA olisi ColorMapillinen, se olisi tässä...
        
        Tga.ImageData = new unsigned char [Tga.ImageWidth * Tga.ImageHeight * Tga.Components];
        
        //ladataan ImageData, jonka järjestys riippuu ImageType:sta...
        switch(Tga.ImageType)
        {
            //Uncompessed TrueColor: ImageData on on pötkönä tiedostossa: BGR(A)BGR(A)BGR(A)...
            case UncompessedTrueColorTGA:
                for(long i=0; i<Tga.ImageWidth * Tga.ImageHeight * Tga.Components; i++)
                {
                    Tiedosto.read((char *)&Tga.ImageData[i], 1);
                }
            break;


            //RLE TrueColor: ImageData on osittain pötköä osittain "nipuissa"
            case RLETrueColorTGA:

                while(ImageTotalPixelCount < (Tga.ImageWidth * Tga.ImageHeight))
                {
                    //ladataan ensiksi paketti, joka on joko RawPacket (viimeinen bitti: 0) tai RLPacket (viimeinen bitti: 1)
                    //saamme myös tiedon pikselien määrästä ennen uutta pakettia
                    Tiedosto.read((char *)&Packet, 1);
                    
                    //jos Packet:n viimeinen bitti on 0 (eli RawPacket), sen arvo on enintään 127; ja toisin päin...
                    if(Packet < 128){ PacketPixelCount = Packet + 1;        Packet = RawPacket; }
                                else{ PacketPixelCount = Packet - 128 + 1;  Packet = RLPacket; }

                    switch(Packet)
                    {
                        //RawPacket: pikseleitä luetaan tiedostosta paketin osoittaman määrän verran...
                        case RawPacket:
                            for(int i=0; i<PacketPixelCount; i++)
                            {
                                for(int n=0; n<Tga.Components; n++)
                                {
                                    Tiedosto.read((char *)&Tga.ImageData[ImageTotalPixelCount * Tga.Components + n], 1);
                                }
                                ImageTotalPixelCount++;
                            }
                        break;
                        
                        //RLPacket: luetaan yksi pikseli tiedostosta
                        //          ja pistetään paketin osoittaman määrän verran pikseleitä samaksi
                        case RLPacket:
                            
                            for(int i=0; i<Tga.Components; i++)
                            {
                                Tiedosto.read((char *)&RLEComponents[i], 1);
                            }
                            for(int i=0; i<PacketPixelCount; i++)
                            {
                                for(int n=0; n<Tga.Components; n++)
                                {
                                    Tga.ImageData[ImageTotalPixelCount * Tga.Components + n] = RLEComponents[n];
                                }
                                ImageTotalPixelCount++;
                            }
                        break;                        
                    }
                }
            break;


            default: return false; break; //jos ImageType ei ole 2 tai 10: VIRHE
        }

        Tekstuuri.Data = new unsigned char [Tga.ImageWidth * Tga.ImageHeight * Tga.Components];

        //siirretään Tga:n ImageData Tekstuurin Dataan
        //vaihtaen samalle komponenttien järjestystä BGR(A):sta RGB(A):ksi
        for(long i=0; i<Tga.ImageWidth * Tga.ImageHeight * Tga.Components; i+=Tga.Components)
        {
            Tekstuuri.Data[i]   = Tga.ImageData[i+2];
            Tekstuuri.Data[i+1] = Tga.ImageData[i+1];
            Tekstuuri.Data[i+2] = Tga.ImageData[i];
            if(Tga.Components == 4) Tekstuuri.Data[i+3] = Tga.ImageData[i+3];
        }

        delete [] Tga.ImageData; Tga.ImageData = NULL;

        Tekstuuri.Leveys = Tga.ImageWidth;
        Tekstuuri.Korkeus = Tga.ImageHeight;
        Tekstuuri.Komponentit = Tga.Components;
        
        if(Tekstuuri.Komponentit == 3){Tekstuuri.Type = GL_RGB;}
        if(Tekstuuri.Komponentit == 4){Tekstuuri.Type = GL_RGBA;}


        Tiedosto.close();
    }
    
    return true;
}







bool Lataa3DS(char *TiedostoNimi, MALLI3D &Malli3D)
{
    
    _3DS Temp3DS;
 
    unsigned short ChunkID;
    unsigned int ChunkLenght;
    unsigned char Char;
    unsigned short FaceFlags;

    ifstream Tiedosto(TiedostoNimi, ios_base::binary);
    if(Tiedosto.is_open())
    {
        while(Tiedosto.peek() != EOF)
        {
            Tiedosto.read((char *)&ChunkID, 2);
            Tiedosto.read((char *)&ChunkLenght, 4);
       
            switch(ChunkID)
            {
                case MAIN_CHUNK: break;

                case _3D_EDITOR_CHUNK: break;

                case OBJECT_BLOCK:
                    for(int i=0; i<20; i++)
                    {
                        Tiedosto.read((char *)&Char, sizeof(unsigned char));
                        Temp3DS.Nimi[i] = Char;
                        if(Char == '\0'){ break; }

                    }

                break;

                case TRIANGULAR_MESH: break;

                case VERTICES_LIST:
                    Tiedosto.read((char *)&Temp3DS.VerteksienLKM, sizeof(unsigned short));
                        Temp3DS.Verteksit = new GLfloat *[Temp3DS.VerteksienLKM];

                    for(int i=0; i<Temp3DS.VerteksienLKM; i++)
                    {
                        Temp3DS.Verteksit[i] = new GLfloat [3];
                        Tiedosto.read((char *)&Temp3DS.Verteksit[i][0], sizeof(float));
                        Tiedosto.read((char *)&Temp3DS.Verteksit[i][1], sizeof(float));
                        Tiedosto.read((char *)&Temp3DS.Verteksit[i][2], sizeof(float));
                    }
                break;

                case FACES_DESCRIPTION:
                     Tiedosto.read((char *)&Temp3DS.TahkojenLKM, sizeof(unsigned short));
                        Temp3DS.Tahkot = new unsigned short *[Temp3DS.TahkojenLKM];

                    for(int i=0; i<Temp3DS.TahkojenLKM; i++)
                    {
                        Temp3DS.Tahkot[i] = new unsigned short [3];
                        Tiedosto.read((char *)&Temp3DS.Tahkot[i][0], sizeof(unsigned short));
                        Tiedosto.read((char *)&Temp3DS.Tahkot[i][1], sizeof(unsigned short));
                        Tiedosto.read((char *)&Temp3DS.Tahkot[i][2], sizeof(unsigned short));
                        Tiedosto.read((char *)&FaceFlags, sizeof(unsigned short));
                    }
                break;

                //case FACES_MATERIAL: break;

                case MAPPING_COORDINATES_LIST:
                     Tiedosto.read((char *)&Temp3DS.TeksKoordienLKM, sizeof(unsigned short));
                        Temp3DS.TeksKoordit = new GLfloat *[Temp3DS.TeksKoordienLKM];

                    for(int i=0; i<Temp3DS.TeksKoordienLKM; i++)
                    {
                        Temp3DS.TeksKoordit[i] = new GLfloat [2];
                        Tiedosto.read((char *)&Temp3DS.TeksKoordit[i][0], sizeof(float));
                        Tiedosto.read((char *)&Temp3DS.TeksKoordit[i][1], sizeof(float));

                    }
                break;

                default: 
                    Tiedosto.seekg( ChunkLenght - 6, ios_base::cur);
                break;

            }
        }
        
        Malli3D.VerteksienLKM = Temp3DS.TahkojenLKM * 3;
        Malli3D.Verteksit = new GLfloat [Malli3D.VerteksienLKM * 3];
        Malli3D.TeksKoordit = new GLfloat [Malli3D.VerteksienLKM * 3];
        for(int i=0; i<Temp3DS.TahkojenLKM; i++)
        {
            for(int n=0; n<3; n++)
            {
                Malli3D.Verteksit[i*9 + n*3] = Temp3DS.Verteksit[Temp3DS.Tahkot[i][n]][0];
                Malli3D.Verteksit[i*9 + n*3 +1] = Temp3DS.Verteksit[Temp3DS.Tahkot[i][n]][1];
                Malli3D.Verteksit[i*9 + n*3 + 2] = Temp3DS.Verteksit[Temp3DS.Tahkot[i][n]][2];
                
                Malli3D.TeksKoordit[i*6 + n*2] = Temp3DS.TeksKoordit[Temp3DS.Tahkot[i][n]][0];
                Malli3D.TeksKoordit[i*6 + n*2 + 1] = Temp3DS.TeksKoordit[Temp3DS.Tahkot[i][n]][1];
            }
        }

        Tiedosto.close();
        return true;
    }

    else{ return false; }
}







































